package fz.vrd.library.utils;

import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;


/**
 * 文件操作工具类
 */
public class FileUtils  {

    static String TAG = FileUtils.class.getName();

    /**
     * 判断是否有sd卡
     */
    public static boolean existSDCard() {
        return getExternalStorageState().equals(
                android.os.Environment.MEDIA_MOUNTED);
    }

    /**
     * sd卡是否可读
     */
    public static boolean isReadSDCard() {
        return getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)
                || Environment.MEDIA_MOUNTED_READ_ONLY.equals(getExternalStorageState());
    }

    /**
     * sd卡状态
     */
    public static String getExternalStorageState() {
        return android.os.Environment.getExternalStorageState();
    }

    /**
     * 外置存储卡的路径
     *
     * @return
     */
    public static String getExternalStorePath() {
        return existSDCard() ? Environment.getExternalStorageDirectory().getAbsolutePath() : null;
    }

    public static String getDownloadCacheDirectory() {

        return Environment.getDownloadCacheDirectory().getPath();
    }

    /**
     * 获取asseat 目录下的json文件的数据
     *
     * @param mContext
     * @param fileName json文件名
     * @return
     */
    public static String getAssetsFile(Context mContext, String fileName) {

        StringBuilder builder = new StringBuilder();
        try {
            InputStreamReader isr = new InputStreamReader(mContext.getAssets().open(fileName), "UTF-8");
            BufferedReader br = new BufferedReader(isr);
            String line;
            while ((line = br.readLine()) != null) {
                builder.append(line);
            }
            br.close();
            isr.close();
            return builder.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 获取Raw文件
     * @param rawId
     * @return
     */
    public String openRawResource(Context context, int rawId) {
        InputStream inputStream = null;
        inputStream = context.getResources().openRawResource(rawId);
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuilder builder = new StringBuilder();
        String line = null;
        try {
            while (true) {
                if (!((line = reader.readLine()) != null)) {
                    builder.append(line);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return builder.toString();
    }

    /**
     * 把Assets的下面的文件写入到其他文件
     *
     * @param context
     * @param assetsFileName Assets下面的文件名称
     * @param filePath       需要写入的文件路径
     * @return
     */
    public static boolean writeAssetsFileToFile(Context context, String assetsFileName, String filePath) {
        if (context == null || TextUtils.isEmpty(assetsFileName) || TextUtils.isEmpty(filePath)) {
            return false;
        }
        File file = new File(filePath.substring(0, filePath.lastIndexOf("/") + 1));
        if (!file.exists()) {
            file.mkdir();
        }
        if (!file.exists()) {
            file.mkdirs();
        }
        try {
            InputStream open = context.getResources().getAssets().open(assetsFileName);
            FileOutputStream fos = new FileOutputStream(filePath);
            byte[] buffer = new byte[1024];
            int count = 0;
            while ((count = open.read(buffer)) > 0) {
                fos.write(buffer, 0, count);
            }
            fos.close();
            open.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(TAG, "=writeAssetsFileToFile====" + e.getMessage());
            return false;
        }
    }

    /**
     * 获取公共文件对应的目录
     * @param type：
     * DIRECTORY_MUSIC：音乐类型
     * DIRECTORY_PICTURES：图片类型
     * DIRECTORY_MOVIES：电影类型
     * DIRECTORY_DCIM：照片类型
     * DIRECTORY_DOWNLOADS：下载文件类型
     * DIRECTORY_DOCUMENTS：文档类型
     * DIRECTORY_RINGTONES：铃声类型
     * DIRECTORY_ALARMS：闹钟提示音类型
     * DIRECTORY_NOTIFICATIONS：通知提示音类型
     * DIRECTORY_PODCASTS：播客音频类型
     *
     * 小技巧：如果不希望系统的媒体扫描器访问我们的媒体文件，可以在媒体文件所在的目录
     * 下新建一个名为.nomedia 的空文件，这会阻止媒体扫描器归类我们的文件并提供给其他应用。
     *
     */
    public static File getExternalStoragePublicDirectory(String type){

        return Environment.getExternalStoragePublicDirectory(type);
    }

    /**
     * 私有文件：对于应用私有的文件，则应该使用 Context 的 getExternalFilesDir 方法访问外部存储中的私有存储目录，媒体扫描器不会扫描这些目录。
     * 路径参考： /storage/emulated/0/Android/data/包名/files
     *
     * @param type：可以为这个方法传入一个String 类型的type参数，用于获取私有存储目录中相应的媒体文件子目录。当然，也可以传入null 直接获取私有存储的根目录。这个方法的返回值也是一个 File 对象。
     *      {@link android.os.Environment#DIRECTORY_MUSIC},
     *      {@link android.os.Environment#DIRECTORY_PODCASTS},
     *      {@link android.os.Environment#DIRECTORY_RINGTONES},
     *      {@link android.os.Environment#DIRECTORY_ALARMS},
     *      {@link android.os.Environment#DIRECTORY_NOTIFICATIONS},
     *      {@link android.os.Environment#DIRECTORY_PICTURES}, or
     *      {@link android.os.Environment#DIRECTORY_MOVIES}.
     *
     *  注意，某些移动设备可能既提供了内置存储器作为外部存储空间，同时又提供了SD 卡作为外部存储空间。也就是说，在这些设备中外部存储实际上包含了两块磁盘。在Android 4.3（API 18）及以下，
     *            Context 的 getExternalFilesDir 方法仅仅会返回内置存储器对应的外部存储控件，而无法访问 SD 卡对应的存储空间。从 Android 4.4（API 19）开始，
     *            Context 新增了getExternalFilesDirs 方法。这个方法的返回值是一个 File 数组，包含两个对象（可能为null），这样就可以实现对内置存储器和 SD 卡的访问。
     *            数组的第一个对象默认是外部主存储，官方的开发建议是除非这个位置已满或不可用，否则应该使用这个位置。
     *
     *
     */
    public static File getExternalFilesDir(Context context,String type){
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT){
            return context.getExternalFilesDir(type);
        }else{
           File[] files = context.getExternalFilesDirs(type);
            return files != null && files.length > 0 ? files[0] : null;
        }
    }


    /**
     * 对于应用的私有缓存数据，可以保存在内部存储的缓存目录中，关键方法是Context 的getCacheDir 方法。
     * 路径参考： /storage/emulated/0/Android/data/包名/cache
     *
     *  说明参考：getExternalFilesDir（）
     */
    public static File getExternalCacheDir(Context context){

        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT){
            return context.getExternalCacheDir();
        }else{
            File[] files = context.getExternalCacheDirs();
            return files != null && files.length > 0 ? files[0] : null;
        }
    }

    /**
     * 获取缓存路径
     * 路径参考：/data/user/0/包名/cache
     */
    public static File getCacheDir(Context context){
        File file = new File("");
        file.list(new FilenameFilter() {

            @Override
            public boolean accept(File file, String s) {
                return s.endsWith(".png");
            }
        });
        return context.getCacheDir();
    }

    /**
     * 文件是否存在
     */
    public static boolean isExists(File file) {
        return file == null ? false : file.exists();
    }

    /**
     * 获取文件名
     */
    public static String getFileName(File file) {
        if (file == null) {
            throw new NullPointerException();
        }

        return file.getName();
    }

    public static String getFileParent(File file) {
        if (file == null) {
            throw new NullPointerException();
        }

        return file.getParent();
    }

    /**
     * 是否为目录文件夹
     */
    public static boolean isDirectory(File file) {
        return file == null ? false : file.isDirectory();
    }

    /**
     * 创建文件
     */
    public static File createFile(String dir, String fileName) {
        try {
            File file = new File(dir);

            if (!file.exists()) {
                file.mkdirs();
            }

            File file1 = new File(dir, fileName);
            if (!file1.exists()) {
                file1.createNewFile();
            }
            return file;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 删除文件
     */
    public static boolean deleteFile(File file) {
        boolean flag = false;
        // 路径为文件且不为空则进行删除
        if (file != null && file.exists() && file.isFile()) {
            file.delete();
            flag = true;
        }
        return flag;
    }

    /**
     * 删除文件夹
     */
    public static boolean deleteDirectory(File file) {
        if (file == null) {
            return false;
        }
        //如果dir对应的文件不存在，或者不是一个目录，则退出
        if (!file.exists() || !file.isDirectory()) {
            return false;
        }
        boolean flag = true;
        //删除文件夹下的所有文件(包括子目录)
        File[] files = file.listFiles();
        for (int i = 0; i < files.length; i++) {
            //删除子文件
            if (files[i].isFile()) {
                flag = deleteFile(files[i]);
                if (!flag) {
                    break;
                }
            } else {
                flag = deleteDirectory(files[i]);
                if (!flag) {
                    break;
                }
            }
        }
        if (!flag) {
            return false;
        }
        file.deleteOnExit();

        return file.exists();
    }

    /**
     * 读取文件内容
     */
    public static String readFile(File file) throws IOException {

        return readFile(file, "UTF-8");
    }

    public static String readFile(File file, String charsetName) throws IOException {

        BufferedReader bufferedReader = new BufferedReader(
                new InputStreamReader(new FileInputStream(file), charsetName));
        StringBuffer sb = new StringBuffer();
        String line;
        if (bufferedReader != null) {
            while ((line = bufferedReader.readLine()) != null) {
                sb.append(line);
            }
            bufferedReader.close();
        }
        return sb.toString();
    }


    /**
     * 复制文件
     *
     * @param copyFile : 复制的文件
     * @param file     : 原始文件
     */
    public static boolean copyFile(File file, File copyFile)  {
        try {
            InputStream open = new FileInputStream(file);
            FileOutputStream fos = new FileOutputStream(copyFile);
            byte[] buffer = new byte[1024];
            int count = 0;
            while ((count = open.read(buffer)) > 0) {
                fos.write(buffer, 0, count);
            }
            fos.close();
            open.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 写入文件
     *
     * @param file : 文件
     * @param info : 写入内容
     */
    public static boolean writeFileInfo(File file, String info)   {
        try {
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(info.getBytes(StandardCharsets.UTF_8));
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public static boolean writeFileInfo(FileWriter fileWriter, String info)   {
        try {
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
            bufferedWriter.write(info);
            bufferedWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public static boolean writeFileInfo(FileOutputStream fileOutputStream, String info)   {
        try {
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
            outputStreamWriter.write(info);
            outputStreamWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public static boolean writeFileInfo(PrintWriter printWriter, String info)   {
        try {
            printWriter.println(info);
            printWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }


    /**
     * 创建一个临时文件
     *
     * @param prefix:             文件前缀  长度不得小于3
     * @param suffix：文件后缀名        默认 .tmp
     * @param directory：指定文件目录，默认 data/user/0/包名/cache
     */
    public static File createTempFile(String prefix, String suffix, File directory) {

        try {
            return File.createTempFile(prefix, suffix, directory);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}
